/*
 * Copyright 2007-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.paoding.rose.web.impl.mapping;

import net.paoding.rose.web.annotation.ReqMethod;
import net.paoding.rose.web.impl.thread.MatchResult;

/**
 * 
 * @author zhiliang.wang
 *
 * @param <T>
 */
public class SimpleMapping<T> extends AbstractMapping<T> {
	protected int mode;
	private MatchResult matchResult;
	
	public SimpleMapping(String path, ReqMethod[] methods, T target) {
		this(path, MappingFactory.MODE_EQUALS, methods, target);
	}

	public SimpleMapping(String path, int mode, ReqMethod[] methods, T target) {
		super(path, methods, target);
		this.mode = mode;
		matchResult = new MatchResult();
		matchResult.setMatchedString(this.path);
	}

	@Override
	public int compareTo(Mapping<T> o) {
		if (o instanceof SimpleMapping) {
			SimpleMapping<T> so = ((SimpleMapping<T>) o);
			int c = -this.path.compareTo(so.path);
			if (c == 0) {
				boolean e = "*".equals(this.requestMethods);
				boolean n = "*".equals(so.requestMethods);
				if (e && n) {
					return 0;
				} else if (!e && !n) {
					return isMethodReplicated(so) ? 0 : 
						this.requestMethods.length()- so.requestMethods.length();
				} else {
					return e ? 1 : -1;
				}
			}
			return c;
		}
		return -o.compareTo(this);
	}

	@Override
	public MatchResult match(String path, String requestMethod) {
		if (path.length() < this.path.length()) {
			return null;
		}
		if (!isRequestMethodSupported(requestMethod)) {
			return null;
		}
		boolean matched = false;
		switch (mode) {
		case MappingFactory.MODE_STARTS_WITH:
			matched = path.startsWith(this.path);
			if (matched && path.length() > this.path.length()
					&& path.charAt(this.path.length()) != '/') {
				matched = false;
			}
			break;
		case MappingFactory.MODE_EQUALS:
			if (path.length() > this.path.length()) {
				if (path.length() == this.path.length() + 1) {
					matched = path.startsWith(this.path);
					if (matched && path.charAt(this.path.length()) != '/') {
						matched = false;
					}
				}
			}
			else {
				matched = path.equals(this.path);
			}
			break;
		default:
			break;
		}
		if (matched) {
			return matchResult;
		}
		return null;
	}

}
